package com.beaven.imserver.net.factory;

import com.beaven.imserver.net.bean.api.base.PushModel;
import com.beaven.imserver.net.bean.card.GroupCard;
import com.beaven.imserver.net.bean.card.MessageCard;
import com.beaven.imserver.net.bean.card.UserCard;
import com.beaven.imserver.net.bean.db.Group;
import com.beaven.imserver.net.bean.db.GroupMember;
import com.beaven.imserver.net.bean.db.Message;
import com.beaven.imserver.net.bean.db.PushHistory;
import com.beaven.imserver.net.bean.db.User;
import com.beaven.imserver.net.utils.HibUtil;
import com.beaven.imserver.net.utils.PushUtil;
import com.beaven.imserver.net.utils.TextUtil;
import com.google.common.base.Strings;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * author: Beaven
 * time: 2017/5/31 18:25
 */
public class PushFactory {

  // 发送一条消息，并在当前的发送历史记录中存储记录
  public static void pushNewMessage(User sender, Message message) {
    if (sender == null || message == null) {
      return;
    }

    // 消息卡片用于发送
    MessageCard card = new MessageCard(message);
    // 要推送的字符串
    String entity = TextUtil.toJson(card);

    // 发送者
    PushUtil dispatcher = new PushUtil();

    if (message.getGroup() == null
        && Strings.isNullOrEmpty(message.getGroupId())) {
      // 给朋友发送消息

      User receiver = UserFactory.findById(message.getReceiverId());
      if (receiver == null) {
        return;
      }

      // 历史记录表字段建立
      PushHistory history = new PushHistory();
      // 普通消息类型
      history.setEntityType(PushModel.ENTITY_TYPE_MESSAGE);
      history.setEntity(entity);
      history.setReceiver(receiver);
      // 接收者当前的设备推送Id
      history.setReceiverPushId(receiver.getPushId());

      // 推送的真实Model
      PushModel pushModel = new PushModel();
      // 每一条历史记录都是独立的，可以单独的发送
      pushModel.add(history.getEntityType(), history.getEntity());

      // 添加数据至发送者
      dispatcher.addMessage(receiver, pushModel);

      // 保存到数据库
      HibUtil.queryOnly(session -> session.save(history));
    } else {

      Group group = message.getGroup();
      // 因为延迟加载情况可能为null，需要通过Id查询
      if (group == null) {
        group = GroupFactory.findById(message.getGroupId());
      }

      // 如果群真的没有，则返回
      if (group == null) {
        return;
      }

      // 给群成员发送消息
      Set<GroupMember> members = GroupFactory.getMembers(group);
      if (members.size() == 0) {
        return;
      }

      // 过滤自己
      members = members.stream()
          .filter(groupMember -> !groupMember.getUserId()
              .equalsIgnoreCase(sender.getId()))
          .collect(Collectors.toSet());
      if (members.size() == 0) {
        return;
      }

      // 一个历史记录列表
      List<PushHistory> histories = new ArrayList<>();

      addGroupMembersPushModel(dispatcher, // 推送的发送者
          histories, // 数据库要存储的列表
          members,    // 所有的成员
          entity, // 要发送的数据
          PushModel.ENTITY_TYPE_MESSAGE); // 发送的类型

      // 保存到数据库的操作
      HibUtil.queryOnly(session -> {
        for (PushHistory history : histories) {
          session.saveOrUpdate(history);
        }
      });
    }

    // 发送者进行真实的提交
    dispatcher.send();
  }

  /**
   * 给群成员构建一个消息，
   * 把消息存储到数据库的历史记录中，每个人，每条消息都是一个记录
   */
  private static void addGroupMembersPushModel(PushUtil dispatcher,
      List<PushHistory> histories,
      Set<GroupMember> members,
      String entity,
      int entityTypeMessage) {
    for (GroupMember member : members) {
      // 无须通过Id再去找用户
      User receiver = member.getUser();
      if (receiver == null) {
        return;
      }

      // 历史记录表字段建立
      PushHistory history = new PushHistory();
      history.setEntityType(entityTypeMessage);
      history.setEntity(entity);
      history.setReceiver(receiver);
      history.setReceiverPushId(receiver.getPushId());
      histories.add(history);

      // 构建一个消息Model
      PushModel pushModel = new PushModel();
      pushModel.add(history.getEntityType(), history.getEntity());

      // 添加到发送者的数据集中
      dispatcher.addMessage(receiver, pushModel);
    }
  }

  // 用户退出推送
  public static void pushLogout(User receiver) {
    PushUtil dispatcher = new PushUtil();
    PushModel model = new PushModel();
    model.add(PushModel.ENTITY_TYPE_LOGOUT, "");
    dispatcher.addMessage(receiver, model);
    dispatcher.send();
    Logger.getLogger("PushLogout")
        .log(Level.INFO, receiver.getName() + "--userId---" + receiver.getPushId());
  }

  // 好友添加，删除推送
  public static void pushUser(int entType, User receiver, UserCard card) {
    String content = TextUtil.toJson(card);
    PushUtil dispatcher = new PushUtil();
    PushModel model = new PushModel();
    model.add(entType, content);
    dispatcher.addMessage(receiver, model);
    dispatcher.send();
    Logger.getLogger("pushUser")
        .log(Level.INFO,
            "pushUser-" + receiver.getName() + "--userId---" + receiver.getPushId());
  }

  // 群组成员添加，删除
  public static void pushGroupMember(int entType, User receiver, GroupMember group) {
    GroupCard card = new GroupCard(group);
    String content = TextUtil.toJson(card);
    PushUtil dispatcher = new PushUtil();
    PushModel model = new PushModel();
    model.add(entType, content);
    dispatcher.addMessage(receiver, model);
    dispatcher.send();
  }

  // 推送群组成员删除群
  public static void pushGroupDelete(Group group) {
    Set<GroupMember> members = GroupFactory.getMembers(group);
    if (members.size() == 0) {
      return;
    }
    members = members.stream()
        .filter(groupMember -> groupMember.getPermissionType() == GroupMember.NOTIFY_LEVEL_NONE)
        .collect(
            Collectors.toSet());
    PushUtil dispatcher = new PushUtil();
    for (GroupMember member : members) {
      User receiver = member.getUser();
      GroupCard card = new GroupCard(member);
      PushModel model = new PushModel();
      String content = TextUtil.toJson(card);
      model.add(PushModel.ENTITY_TYPE_DELETE_GROUP, content);
      dispatcher.addMessage(receiver, model);
    }

    dispatcher.send();
  }
}
